#!/bin/bash -e
#   * compile instructions: put this file in
#   *         `steamapps/common/Dyson Sphere Program/CustomMod`
#   * folder, open a terminal in the same folder, and execute:
#   *
#   * ```
#   *     chmod +x ${file}.cs
#   *     ./${file}.cs
#   * ```
#   *
#   * then the mod will be compiled automatically.
#   *
#   * Here we wrote a shebang like file, which is correct
#   * in my computer (Manjaro XFCE), if such script do not work
#   * in your computer, you could just try the instructions below :

if [ -z "$__DOTNET_CSC" ]; then
    export __DOTNET_CSC="`find /usr/share/dotnet -type f -name dotnet` `find /usr/share/dotnet -name csc.dll`"
    echo '$'"__DOTNET_CSC not set yet, you should execute"
    echo "export __DOTNET_CSC='$__DOTNET_CSC'"
    echo "manually, or this alert will occur each time you execute this script."
fi

__MODE_VERBOSE=77 # is the line number of "#define VERBOSE", may be modified
__MODE_DEBUG__=$((__MODE_VERBOSE+1))
__MODE_RELEASE=$((__MODE_DEBUG__+1))

case $1 in
    V)       _MODE__SELECT_=$__MODE_VERBOSE     ;;
    v)       _MODE__SELECT_=$__MODE_VERBOSE     ;;
    VERBOSE) _MODE__SELECT_=$__MODE_VERBOSE     ;;
    verbose) _MODE__SELECT_=$__MODE_VERBOSE     ;;
    D)       _MODE__SELECT_=$__MODE_DEBUG__     ;;
    d)       _MODE__SELECT_=$__MODE_DEBUG__     ;;
    DEBUG)   _MODE__SELECT_=$__MODE_DEBUG__     ;;
    debug)   _MODE__SELECT_=$__MODE_DEBUG__     ;;
    *)       _MODE__SELECT_=$__MODE_RELEASE     ;;
esac

export GAME_NAME="${0%\.cs}" # now, file name should be equals to ${GAME_NAME}.cs, the benefit is, we could only change the name, rather than change filename and $GAME_NAME.
export FILE_NAME="$0"

( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_ ) | $__DOTNET_CSC -nologo -t:library \
  -r:'../BepInEx/core/BepInEx.dll' \
  -r:'../BepInEx/core/0Harmony.dll' \
  -r:'../BepInEx/core/BepInEx.Harmony.dll' \
  `[ -e "../${GAME_NAME}_Data/Managed/netstandard.dll" ] && echo "-r:\"../${GAME_NAME}_Data/Managed/netstandard.dll\""` \
  -r:"../${GAME_NAME}_Data/Managed/System.dll" \
  -r:"../${GAME_NAME}_Data/Managed/System.Core.dll" \
  -r:"../${GAME_NAME}_Data/Managed/UnityEngine.dll" \
  -r:"../${GAME_NAME}_Data/Managed/UnityEngine.CoreModule.dll" \
  -r:"../${GAME_NAME}_Data/Managed/mscorlib.dll" \
  -r:"../${GAME_NAME}_Data/Managed/Assembly-CSharp.dll" \
  `[ -e "../${GAME_NAME}_Data/Managed/Assembly-CSharp-firstpass.dll" ] && echo "-r:\"../${GAME_NAME}_Data/Managed/Assembly-CSharp-firstpass.dll\""` \
  -out:'../BepInEx/plugins/'"${FILE_NAME%.*}".dll \
  -optimize \
  - && rm -f "../BepInEx/config/Neutron3529.Cheat.cfg";

if [ -n "$2" ]; then
    git add ${FILE_NAME}
    case $2 in
        R) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        r) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        RANDOM) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        random) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        U) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        u) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        UPLOAD) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        upload) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        *) git commit -am "$2" ;;
    esac
    git push
fi
exit


#define VERBOSE // the line of __MODE_VERBOSE
#define DEBUG

/*
 * 修改心得：
 * 这个游戏很容易改出死锁
 * 我并不知道作者是如何用巧妙的手法避开死锁的（大抵是作者可以直接访问private而我们不可以）
 *
 * 在修改时候，我们不难发现，读CacheMgr.UID的时候可能会导致死锁，因为这个需要初始化CacheMgr，而初始化又可能读取到需要读CacheMgr.UID才能判断是否要特殊处理的数值
 * 这里的解法是把UID后移，通过读取武将所在国家是否是更新过的，以确定我们是否已经可以读取CacheMgr.UID
 *
 * 当然另一个改法可能是get/set CacheMgr.UID的时候顺手set掉我们精心准备的全局变量
 * 无论如何，现在可以正常修改了。
 */

using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;

using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

namespace Cheat
{
    [BepInPlugin("Neutron3529.Cheat", "Cheat", "0.1.0")]
    public class Cheat : BaseUnityPlugin {
        public static int CID=-1;
        public static int AddForce=1000;
        public static int AddWit=1000;
        public static int AddPolity=1000;
        public static int AddCharm=1000;
        public static int AddASd=100;
        public static int AddMSd=100;
#if DEBUG
        public static Action<string> logger;
#endif
        void Start() {
            var harmony=new Harmony("Neutron3529.Eagarlnia");
#if DEBUG
            logger=Logger.LogInfo;
            logger("Eagarlnia-开始注入");
#endif
            if ((AddForce=Config.Bind<int>("config", "AddForce", 1000, "额外Force").Value)>0){
                harmony.PatchAll(typeof(MHeroInfoForce));
#if DEBUG
                logger("Eagarlnia-额外Force-加载完成");
#endif
            }
            if ((AddWit=Config.Bind<int>("config", "AddWit", 1000, "额外Wit").Value)>0){
                harmony.PatchAll(typeof(MHeroInfoWit));
#if DEBUG
                logger("Eagarlnia-额外Wit-加载完成");
#endif
            }
            if ((AddPolity=Config.Bind<int>("config", "AddPolity", 1000, "额外Polity").Value)>0){
                harmony.PatchAll(typeof(MHeroInfoPolity));
#if DEBUG
                logger("Eagarlnia-额外Polity-加载完成");
#endif
            }
            if ((AddCharm=Config.Bind<int>("config", "AddCharm", 1000, "额外Charm").Value)>0){
                harmony.PatchAll(typeof(MHeroInfoCharm));
#if DEBUG
                logger("Eagarlnia-额外Charm-加载完成");
#endif
            }
            if ((AddASd=Config.Bind<int>("config", "AddASd", 100, "额外攻速").Value)>0){
                harmony.PatchAll(typeof(MHeroInfoASd));
#if DEBUG
                logger("Eagarlnia-额外攻速-加载完成");
#endif
            }
            if ((AddMSd=Config.Bind<int>("config", "AddMSd", 100, "额外移速").Value)>0){
                harmony.PatchAll(typeof(MHeroInfoMSd));
#if DEBUG
                logger("Eagarlnia-额外移速-加载完成");
#endif
            }
            if (AddForce>0||AddWit>0||AddPolity>0||AddCharm>0){
                harmony.PatchAll(typeof(MHeroInfoRefreshHeroData));
#if DEBUG
                logger("Eagarlnia-刷新国家时刷新ID-加载完成");
#endif
            }
#if DEBUG
            logger("Eagarlnia-加载完成");
#endif
        }
        [HarmonyDebug]
        [HarmonyPatch(typeof(Game.Entity.CacheEntity.MHeroInfo), "RefreshHeroData")]
        class MHeroInfoRefreshHeroData {
            public static bool Prefix(Game.Entity.CacheEntity.MHeroInfo __instance) {
                if(__instance.CountryID > 0)
                    CID=Game.CacheMgr.UID;
                return true;
            }
        }
        [HarmonyPatch(typeof(Game.Entity.CacheEntity.MHeroInfo), "Force",MethodType.Getter)]
        class MHeroInfoForce {
            public static void Postfix(Game.Entity.CacheEntity.MHeroInfo __instance,ref int __result) {
                if(__instance.CountryID==CID)__result+=AddForce;
            }
        }
        [HarmonyPatch(typeof(Game.Entity.CacheEntity.MHeroInfo), "Polity",MethodType.Getter)]
        class MHeroInfoPolity {
            public static void Postfix(Game.Entity.CacheEntity.MHeroInfo __instance,ref int __result) {
                if(__instance.CountryID==CID)__result+=AddPolity;
            }
        }
        [HarmonyPatch(typeof(Game.Entity.CacheEntity.MHeroInfo), "Wit",MethodType.Getter)]
        class MHeroInfoWit {
            public static void Postfix(Game.Entity.CacheEntity.MHeroInfo __instance,ref int __result) {
                if(__instance.CountryID==CID)__result+=AddWit;
            }
        }
        [HarmonyPatch(typeof(Game.Entity.CacheEntity.MHeroInfo), "Charm",MethodType.Getter)]
        class MHeroInfoCharm {
            public static void Postfix(Game.Entity.CacheEntity.MHeroInfo __instance,ref int __result) {
                if(__instance.CountryID==CID)__result+=AddCharm;
            }
        }
        [HarmonyPatch(typeof(Game.Entity.CacheEntity.MHeroInfo), "ASd",MethodType.Getter)]
        class MHeroInfoASd {
            public static void Postfix(Game.Entity.CacheEntity.MHeroInfo __instance,ref int __result) {
                if(__instance.CountryID==CID)__result+=AddASd;
            }
        }
        [HarmonyPatch(typeof(Game.Entity.CacheEntity.MHeroInfo), "MSd",MethodType.Getter)]
        class MHeroInfoMSd {
            public static void Postfix(Game.Entity.CacheEntity.MHeroInfo __instance,ref int __result) {
                if(__instance.CountryID==CID)__result+=AddMSd;
            }
        }
    }
}
